<script setup lang="ts">
import HelloWorld from '@/components/HelloWorld.vue'
import children from '@/views/chuanzhi/children/children.vue'
import { reactive, ref, toRefs, onMounted, computed, effect, watch, nextTick } from 'vue';
// 一、文件结构
// 二、data
// ref声明响应式数据，用于声明基本数据类型
const name = ref('Jerry')
console.log('ref声明响应式数据，用于声明基本数据类型', name.value);

// 修改
// name.value = 'Tom'
// console.log('修改ref声明响应式数据，用于声明基本数据类型', name.value);

// reactive声明响应式数据，用于声明引用数据类型
const state = reactive({
  name: 'Jerry',
  sex: '男'
})
console.log('reactive声明响应式数据，用于声明引用数据类型', state);

// 修改
state.name = 'Tom'
console.log('修改reactive声明响应式数据，用于声明引用数据类型', state);

// 使用toRefs解构
const { name: string, sex } = toRefs(state)
// template可直接使用{{name}}、{{sex}}
console.log('使用toRefs解构', name.value, sex.value);

// 三、method：声明method方法 并执行
const changeName = () => {
  state.name = 'Tom'
  console.log('changeName', state);
};
changeName()

// 四、computed
const count = ref(1)

// 通过computed获得doubleCount
const doubleCount = computed(() => {
  return count.value * 2
})
effect(() => {
  console.log('effect', doubleCount.value)
})
count.value = 3

// 五、watch
const wstate = reactive({
  count: 1
})
const chanGeCount = () => {
  wstate.count = wstate.count * 2
}
watch(
  () => wstate.count,
  (newVal, oldVal) => {
    // 监听count，没有立即执行、深度监听获取不到count初始值，只能拿到变化后的值
    console.log('watch', wstate.count)
    console.log(`watch监听变化前的数据：${oldVal}`)
    console.log(`watch监听变化后的数据：${newVal}`)
  },
  {
    immediate: true, // 立即执行
    deep: true // 深度监听
  }
)
chanGeCount()

// 六 、props父传子
const menu = [
  {
    id: 1,
    name: '我的待办1'
  }, {
    id: 2,
    name: '我的待办2'
  }]

// 七、子传父 接收子组件触发的方法

const statex = reactive({
  name: 'Jerry'
})
const updataName = (name.value); {
  console.log('updataName');
  state.name = name.value
}

// 八、v-model
const statexx = reactive({
  name: 'Jerry',
  age: 20
})

// 九、nextTick
nextTick(() => {
  // ...
})

// 十、子组件ref变量和defineExpose
// 在标准组件写法里，子组件的数据都是默认隐式暴露给父组件的，但在 script - setup 模式下，所有数据只是默认 return 给
//  template 使用，不会暴露到组件外，所以父组件是无法直接通过挂载 ref 变量获取子组件的数据。
// 如果要调用子组件的数据，需要先在子组件显示的暴露出来，才能够正确的拿到，这个操作，就是由 defineExpose 来完成。子组件ref
// defineExpose无需引入

const childRef = ref('childRef')

// nextTick
nextTick(() => {
  // 获取子组件name
  console.log('nextTick', childRef.value.name)
  // 执行子组件方法
  childRef.value.changeNames()
  console.log('nextTick', childRef.value.name)
})


</script>

<template>
  <!-- 一、文件结构：Vue2中，template标签中只能有一个根元素，在Vue3中没有此限制 -->
  <div class="fath">
    <div>通过computed获得doubleCount：{{ doubleCount }}</div>
    <div>我是father</div>
    <!-- 六、props父传子 -->
    <children :name="statex.name" :menu="menu" @updataName="updataName" />
    <!-- 七、emit子传父 -->
    <children :name="state.name" :menu="menu" @updataName="updataName" />
    <!-- 八、v-model -->
    <children v-model="statexx.name" v-model:age="statexx.age" />
    <!-- 十、子组件ref变量和defineExpose -->
    <children ref="childRef" />
    <!-- 十一、插槽slot -->
    <children class="chacao">
      <!-- // 匿名插槽 -->
      <span>我是默认插槽</span>
      <!-- // 具名插槽 -->
      <template #title>
        <h1>我是具名插槽</h1>
        <h1>我是具名插槽</h1>
        <h1>我是具名插槽</h1>
      </template>
      // 作用域插槽
      <template #footer="{ scope }">
        <footer>作用域插槽——姓名：{{ scope.name }}，年龄{{ scope.age }}</footer>
      </template>
    </children>
    <div class="test">全局样式</div>
  </div>
</template>

<style  lang='scss'>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
.fath {
  border: 1px solid red;
}
.test {
  color: $test-color;
}
.chacao {
  border: 10px solid blue;
}
</style>
